package posomasterworker;


import java.io.BufferedReader;
import java.io.EOFException;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

import mpi.*;

/* Master */
public class POSOMaster{
	/* Attributes of master */
	private int np;
	private int nworkers;
	private int id;
	private double[] timempi = new double[2];
	private double[] time = new double[2];
	
	/* Constructor */
	public POSOMaster(int nworkers_){
		nworkers = nworkers_;
	}
	
	public POSOMaster(){
		nworkers = np;
	}
	
	public void startMPI(String[] args){
		MPI.Init(args);
		id = MPI.COMM_WORLD.Rank();
		np = MPI.COMM_WORLD.Size();
		
		System.out.println("\n\t Processor " + id + " cheking...");	  
		MPI.COMM_WORLD.Barrier();
		  
		/* Check master worker id */
		if(id == 0){
			System.out.println("\n\t Master process id = " +id);
		}
		else{
			System.out.println("\n\t Worker process id = " +id);
		}	  
		MPI.COMM_WORLD.Barrier();
	}
	
	public int getID(){
		return id;
	}
	public int getNumberOfWorkers(){
		return nworkers;
	}
	public int getNumberOfProcessors(){
		return np;
	}
	
	public void startTime(){
		 timempi[0] = MPI.Wtime();
		 time[0] = System.currentTimeMillis();
	}
	public void endTime(){
		timempi[1] = MPI.Wtime();
		time[1] = System.currentTimeMillis();
	}
	
	/* Get time of MPI */
	public double[] getMPITime(){
		return timempi;
	}
	
	/* Get time of system */
	public double[] getTime(){
		return time;
	}
	
	
	/* Send data type INT */
	public void sendData(int[] data, int offset, int count, Datatype type, int dest, int tag ){
		MPI.COMM_WORLD.Send((Object)data, offset, count, type, dest, tag);
	}
	
	/* Send data type DOUBLE */
	public void sendData(double[] data, int offset, int count, Datatype type, int dest, int tag){
		MPI.COMM_WORLD.Send((Object)data, offset, count, type, dest, tag);
	}
	
	/* Receive data type DOUBLE */
	public void receiveData(double[] data, int offset, int count, Datatype type, int source, int tag){
		MPI.COMM_WORLD.Recv((Object)data, offset, count, type, source, tag);
	}
	
	/* Process results */
	public double[] processResult(double[] b){
		double rmin, rmax;
		double gmin, gmax;
		
		gmin = gmax =0;
		/* Process results */
		rmin = b[0];
		rmax = b[1];

		/* Master updates general result */
		if(rmin < gmin) gmin = rmin;
		if(rmax > gmax) gmax = rmax;
		b[0] = gmin;
		b[1] = gmax;
		
		return b;
	}
	public double[] prepareWork(int[] n, int nmax, String filename){
		double ai = 0.0;
		double[] a = new double[nmax];
		
		System.out.println("\n\t Read the number of components");
		  try{
			  //FileReader inputstream = new FileReader("../MPI/bin/minmax.dat");
			  FileReader inputstream = new FileReader(filename);
			  BufferedReader data = new BufferedReader(inputstream);
			  String ncomponents = data.readLine();
			  Integer z = new Integer(ncomponents);
			  n[0]	= z.intValue();
			  
			  System.out.println("\n\t Number of components n = " +n[0]);
			  for(int i = 0; i < n[0]; i++){
				  String value = data.readLine();
				  Double x = new Double(value);
				  ai = x.doubleValue();
				  //System.out.println("a[" +i +"] = " +ai + ", ");
				  a[i] = ai;
			  }
			  System.out.println("\n");
		  }
		  catch(FileNotFoundException e){
			  System.out.println("\n\t File not found");
		  }
		  catch(EOFException endf){
			  System.out.println("\n\t reached end of file");
		  }
		  catch(IOException e){
			  System.out.println("\n\t File reading error");
		  }
		  return a;
	}
}